const path = require('path');
const fs = require('fs');
const fst = require('fs-extra');
const multiparty = require('multiparty');

const fileModel = require('../schemas/file');
const idsModel = require('../schemas/ids');
const config = require('../utils/config');
const { getUploadedList, extractExt, mergeFiles, Util } = require('../utils/util');

const STATIC_TEMP = path.join(__dirname, '../static/uploads/temp'); // 分片临时路径
const STATIC_FILES = path.join(__dirname, '../static/uploads/attachment'); // 附件文件存储路径

// file是标签名
// 前端要设请求头的：'multipart/form-data'
exports.uploadImage = (req, res) => {
  //接收前台POST过来的base64
  const imgData = req.body.imageData;
  const imgName = req.body.imageName;
  //过滤data:URL
  const base64Data = imgData.replace(/^data:image\/\w+;base64,/, '');
  const filename = path.join(__dirname, '../static/uploads/images', imgName);
  const dataBuffer = Buffer.from(base64Data, 'base64');
  //  var dataBuffer = new Buffer(base64Data, 'base64'); // 这是另一种写法
  fs.writeFile(filename, dataBuffer, (err) => {
    if (err) {
      return res.send('写入失败');
    }
    return res.send({
      Code: 200,
      msg: '上传成功！',
      data: `http://127.0.0.1:${config.port}/uploads/images/${imgName}`,
    }); // 成功信息
  });
};

exports.fileUpload = (req, res) => {
  console.log(req.file);
  // const filename = path.join(__dirname, '../static/file', imgName);
  // fs.writeFile(filename, req.file, (err) => {
  //   if (err) {
  //     return res.send('写入失败');
  //   }
  //   return res.send({
  //     Code: 200,
  //     msg: '上传成功！',
  //     data: `http://127.0.0.1:${config.port}/file/${imgName}`,
  //   }); // 成功信息
  // });
};

exports.verifyAttachment = async (req, res) => {
  const { fileName, chunkHashName } = req.body;
  const ext = extractExt(fileName);
  const filePath = path.resolve(STATIC_FILES, `${chunkHashName}${ext}`);
  // 文件是否已存在
  let uploaded = false;
  let uploadedList = [];
  if (fst.existsSync(filePath)) {
    uploaded = true;
  } else {
    uploadedList = await getUploadedList(path.resolve(STATIC_TEMP, chunkHashName));
  }
  return res.send({
    Status: 200,
    Msg: '上传成功！',
    Data: {
      uploaded,
      uploadedList, // 过滤诡异的隐藏文件
    },
  }); // 成功信息
};

exports.uploadChunk = (req, res) => {
  const multipart = new multiparty.Form();
  multipart.parse(req, async (err, field, file) => {
    if (err) {
      console.log(err);
      return;
    }
    const [chunk] = file.chunk;
    const [chunkName] = field.chunkName;
    const [fileName] = field.fileName;
    const [fileHash] = field.fileHash;
    const filePath = path.resolve(STATIC_TEMP, `${fileHash}/${chunkName}`);
    const mergePath = path.resolve(STATIC_FILES, `${fileHash}/${chunkName}`);
    const chunkDir = path.resolve(STATIC_TEMP, fileHash);

    if (fs.existsSync(filePath) || fs.existsSync(mergePath)) {
      return res.send({
        Code: 200,
        msg: '文件已存在！',
        data: {},
      }); // 成功信息
    }

    if (!fst.existsSync(chunkDir)) {
      await fst.mkdirs(chunkDir);
    }
    await fst.move(chunk.path, `${chunkDir}/${chunkName}`);
    return res.send({
      Status: 200,
      msg: '文件分片已上传',
      data: {},
    }); // 成功信息;
  });
};

const mergeFileChunk = async (filePath, fileHash, size) => {
  const chunkDir = path.resolve(STATIC_TEMP, fileHash);
  if (fst.existsSync(filePath)) {
    return;
  }
  // 读chunkDir当前路径下的内容
  let chunkPaths = await fst.readdir(chunkDir);
  // 根据切片下标进行排序
  // 否则直接读取目录的获得的顺序可能会错乱
  chunkPaths.sort((a, b) => a.split('-')[1] - b.split('-')[1]);
  chunkPaths = chunkPaths.map((cp) => path.resolve(chunkDir, cp)); // 转成文件路径
  await mergeFiles(chunkPaths, filePath, size);
};

exports.mergeChunk = async (req, res) => {
  // const data = await resolvePost(req)
  const { fileHash, fileName, size } = req.body;
  const ext = extractExt(fileName);
  const filePath = path.resolve(STATIC_FILES, `${fileHash}${ext}`);
  if (fst.existsSync(filePath)) {
    return res.send({
      Code: 200,
      msg: '文件已存在！',
    });
  }
  const tempDir = path.resolve(STATIC_TEMP, fileHash);
  await mergeFileChunk(filePath, fileHash, size);
  if (fst.existsSync(tempDir)) {
    // 删除分片目录
    fst.rmdirSync(tempDir);
  }
  return res.send({
    Code: 200,
    msg: '文件已上传',
    data: {},
  }); // 成功信息;
};

exports.mergeUpload = async (req, res) => {
  // const data = await resolvePost(req)
  const { fileHash, fileName, size } = req.body;
  const ext = extractExt(fileName);
  const filePath = path.resolve(STATIC_FILES, `${fileHash}${ext}`);

  await mergeFileChunk(filePath, fileHash, size);
  // if (fs.existsSync(tempDir)) {
  //     // 删除分片目录
  //     fs.rmdirSync(tempDir);
  // }
  return res.send({
    Status: 200,
    msg: '文件已上传',
    data: {},
  }); // 成功信息;
};

exports.deleteFile = async (req, res) => {
  const { id, hash, type } = req.query;
  const deleteFilePath = path.resolve(STATIC_FILES, `${hash}${extractExt(type)}`);
  if (fs.existsSync(deleteFilePath)) {
    fs.unlinkSync(deleteFilePath);
  }
  fileModel.deleteOne({ Id: id }, (err, results) => {
    if (err) {
      console.log('删除失败！');
    }
    if (results.deletedCount === 1) {
      res.send({
        Status: 200,
        Message: '删除成功！',
        Data: true,
      });
    }
  });
};

exports.getFileUrlById = async (req, res) => {
  const { id } = req.query;
  fileModel.findOne({ Id: id }, (err, results) => {
    res.send({
      Status: 200,
      Data: `http://127.0.0.1:${config.port}/uploads/attachment/${results.FileHash}${extractExt(results.OriginName)}`,
    });
  });
};

exports.saveFile = async (req, res) => {
  const attachmentInfo = req.body;
  if (Util.isUndefinedOrNullOrWhiteSpace(attachmentInfo.Id)) {
    // 实现Id的自增
    const ids = await idsModel.findOneAndUpdate({ Name: 'File' }, { $inc: { Id: 1 } });
    attachmentInfo.Id = ids.Id;
    attachmentInfo.CreateTime = new Date();
    fileModel.create(attachmentInfo, function (err, results) {
      if (err) {
        console.log('添加失败!');
      }
      return res.send({
        Status: 200,
        Message: '添加成功！',
        Data: results,
      });
    });
  } else {
    fileModel.updateOne({ Id: attachmentInfo.Id }, { $set: attachmentInfo }, function (err, results) {
      if (err) {
        console.log('更新失败!');
      }
      return res.send({
        Status: 200,
        Message: '更新成功！',
        Data: results,
      });
    });
  }
};

exports.getFileList = async (req, res) => {
  const { curPage, pageSize, filters, requestData } = req.body;
  const skipData = (curPage - 1) * pageSize;
  const totalDataLength = await fileModel.find(requestData).count();
  fileModel
    .find(requestData, (err, results) => {
      if (err) {
        console.log('获取列表失败！');
      } else {
        res.send({
          Status: 200,
          Message: '获取列表成功！',
          Data: {
            Data: results,
            Total: totalDataLength,
          },
        });
      }
    })
    .skip(skipData)
    .limit(pageSize);
};

exports.downloadFile = async (req, res) => {
  const { id } = req.query;
  if (Util.isUndefinedOrNullOrWhiteSpace(id)) {
    return res.send({ status: 400, message: '当前文件不存在！' });
  }
  const { FileHash, OriginName, FileName } = await fileModel.findOne({ Id: id });
  const ext = extractExt(OriginName);
  const filePath = path.resolve(STATIC_FILES, `${FileHash}${ext}`);
  if (!fst.existsSync(filePath)) {
    return res.send({
      Code: 200,
      Message: '下载失败！',
    });
  }
  const fileStream = fs.createReadStream(filePath);
  res.writeHead(200, {
    'Content-Type': 'application/force-download;charset=UTF-8',
    'Content-Disposition': 'attachment; filename=' + FileHash,
  });
  fileStream.pipe(res);
};
